
///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2009, Perry L Miller IV
//  All rights reserved.
//  BSD License: http://www.opensource.org/licenses/bsd-license.html
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
//  Helper class for managing transactions.
//
///////////////////////////////////////////////////////////////////////////////

#include "Database/PostgreSQL/Transaction.h"

#include "Usul/Exceptions/Exceptions.h"
#include "Usul/Threads/Guard.h"
#include "Usul/Threads/Mutex.h"

using namespace Database::PostgreSQL;


///////////////////////////////////////////////////////////////////////////////
//
//  Local typedefs.
//
///////////////////////////////////////////////////////////////////////////////

typedef Usul::Threads::Guard < Usul::Threads::Mutex > Guard;


///////////////////////////////////////////////////////////////////////////////
//
//  Helper function to check the given connections.
//
///////////////////////////////////////////////////////////////////////////////

namespace Helper
{
  inline Connection::RefPtr checkConnection ( Connection::RefPtr c )
  {
    if ( false == c.valid() )
    {
      throw Usul::Exceptions::Error
        ( "1979231597", "Cannot have transaction with null connection" );
    }
    return c;
  }
}


///////////////////////////////////////////////////////////////////////////////
//
//  Helper function to finalize a transaction.
//
///////////////////////////////////////////////////////////////////////////////

namespace Helper
{
  inline void finalize ( const std::string &sql, Connection::RefPtr &cr )
  {
    Connection::RefPtr c ( cr );
    cr = Connection::RefPtr();

    if ( true == c.valid() )
    {
      if ( false == sql.empty() )
      {
        c->execute ( sql );
      }
    }
  }
}


///////////////////////////////////////////////////////////////////////////////
//
//  Constructor
//
///////////////////////////////////////////////////////////////////////////////

Transaction::Transaction ( Connection::RefPtr c ) :
  _c ( Helper::checkConnection ( c ) )
{
  _c->execute ( "begin transaction" );
  _c->execute ( "set transaction isolation level serializable" );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Destructor
//
///////////////////////////////////////////////////////////////////////////////

Transaction::~Transaction()
{
  Helper::finalize ( "rollback", _c );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Commit the transaction.
//
///////////////////////////////////////////////////////////////////////////////

void Transaction::commit()
{
  Helper::finalize ( "commit", _c );
}
